package com.icim.csot.exporter.job;

import java.io.File;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.Resource;

import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.icim.core.pojo.FtpConfigure;
import com.icim.core.service.IAlarmSenderService;
import com.icim.core.service.IFtpService;
import com.icim.csot.exporter.csventity.CsotProcessParamCsvEntity;
import com.icim.dao.BisMItemDao;
import com.icim.dao.RetPrdInfoDao;
import com.icim.dao.SpcRetMfgDataDao;
import com.icim.entity.BisMItem;
import com.icim.entity.Ret_prd_info;
import com.icim.entity.Spc_ret_mfg_data;
import com.icim.util.CsvFileWriterUtil;
import com.icim.util.GzCompressUtil;
import static com.icim.def.ComDef.*;

public class CsotExportProcessParamJob {

    private final static Logger logger = LoggerFactory.getLogger(CsotExportProcessParamJob.class);
    private static final String CUS_ID = "007";

    private Timestamp beginTimestamp;
    private Timestamp endTimestamp;
    private String strBeginTime;
    private String strEndTime;
    private FtpConfigure ftpConfigure;
    private int endTimeMak;

    @Resource
    private SpcRetMfgDataDao spcRetMfgDataDao;

    @Resource
    private RetPrdInfoDao retPrdInfoDao;
    @Resource
    private BisMItemDao bisMItemDao;

    private IFtpService ftpService;
  
    
    @Resource
    private IAlarmSenderService alarmSenderService;

    public void subMainProc() {
        logger.info("export process param system running .....");

        /**
         * get time period : begin time & end time
         */
        

        try {
        	getTimePeriod();
			subMainProc2();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			String errorMsg="process数据回传失败，开始时间："+beginTimestamp+"  结束时间："+endTimestamp+"\n"+"失败原因："+e.getMessage();
        	alarmSenderService.sendAlarm1("007",errorMsg);
		}

        logger.info("export process param successfull ......");
    }

    public void subMainProc2() throws Exception {

        /**
         * query table HIS_RET_PRD_INFO by custom_id & time period
         */

        List<Spc_ret_mfg_data> spc_ret_mfg_datas = spcRetMfgDataDao.getCsotSpcDataRecordersByTime(beginTimestamp,
                endTimestamp,"T");

        logger.info("find {} records ....", spc_ret_mfg_datas.size());

        if (spc_ret_mfg_datas.size() == 0) {
            return;
        }

        /**
         * loop sheets make tFile
         */
        List<CsotProcessParamCsvEntity> tEntityList = new LinkedList<CsotProcessParamCsvEntity>();

        spc_ret_mfg_datas = distinctEDCDatas(spc_ret_mfg_datas);
        
        for (Spc_ret_mfg_data spc_ret_mfg_data : spc_ret_mfg_datas) {
            String prd_seq_id = spc_ret_mfg_data.getPrd_seq_id_fk();
            Ret_prd_info retPrdInfo = retPrdInfoDao.getInforById(prd_seq_id);
            String mdlId = checkIsNull(retPrdInfo.getMdl_id_fk());
            String toolId = checkIsNull(spc_ret_mfg_data.getTool_id_fk());
            String opeId = checkIsNull(spc_ret_mfg_data.getOpe_id_fk());
            String mesId = spc_ret_mfg_data.getMes_id_fk();

            List<BisMItem> bisMItems = bisMItemDao.getAllbisMItemByToolIdAndMesId(spc_ret_mfg_data.getTool_id_fk(),
                    spc_ret_mfg_data.getMes_id_fk());
            for (BisMItem bisMItem : bisMItems) {
                CsotProcessParamCsvEntity csvEntity = new CsotProcessParamCsvEntity();
                csvEntity.setFACTORY_ID(CSOT_FACTORY_NAME);
                csvEntity.setBLOCK_ID(prd_seq_id);
                csvEntity.setPRODUCT_ID(mdlId);
                csvEntity.setOWNER_CODE(checkIsNull(retPrdInfo.getGroup_id()));
                csvEntity.setRECIPE_ID(checkIsNull(spc_ret_mfg_data.getAc_recipe_id()));
                csvEntity.setPROCESS_ID(opeId);
                csvEntity.setEQP_ID(toolId);
                csvEntity.setUNIT_ID("");
                csvEntity.setCST_ID(checkIsNull(retPrdInfo.getBox_id_fk()));
                csvEntity.setTIME(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date(spc_ret_mfg_data
                        .getRpt_timestamp().getTime())));
                csvEntity.setPARAM_NAME(checkIsNull(bisMItem.getDataGroup()));
                try {
                    csvEntity.setPARAM_VALUE(spc_ret_mfg_data.getPropertyValue("data_value_" + bisMItem.getDataId()));
                } catch (Exception e) {
                    logger.error(e.getMessage());
                    throw e;
                }
                Double usl = bisMItem.getuSpc();
                Double lsl = bisMItem.getlSpc();
                csvEntity.setUSL(usl.toString());
                csvEntity.setLSL(lsl.toString());
                try {
                    csvEntity.setTARGET((usl + lsl) / 2 + "");
                } catch (Exception e) {
                    logger.warn(e.toString());
                    throw e;
                }
                tEntityList.add(csvEntity);
            }

        }

        List<String[]> bodyList = new ArrayList<String[]>();
        for (CsotProcessParamCsvEntity entity : tEntityList) {
            String[] body = new String[] { entity.getBLOCK_ID(), entity.getFACTORY_ID(), entity.getPRODUCT_ID(),
                    entity.getOWNER_CODE(), entity.getRECIPE_ID(), entity.getPROCESS_ID(), entity.getEQP_ID(),
                    entity.getUNIT_ID(), entity.getCST_ID(), entity.getTIME(), entity.getPARAM_NAME(),
                    entity.getPARAM_VALUE(), entity.getUSL(), entity.getTARGET(), entity.getUSL()

            };
            logger.info(entity.toString());
            bodyList.add(body);

        }

        try {
            String fileName = getFtpConfigure().getLocalProcessParamExportPath() + "/EDC_" + strEndTime + ".csv";
            
            String[] headers = { "BLOCK_ID", "FACTORY_ID", "PRODUCT_ID", "OWNER_CODE", "RECIPE_ID", "PROCESS_ID",
                    "EQP_ID", "UNIT_ID", "CST_ID", "TIME", "PARAM_NAME", "PARAM_VALUE", "USL", "TARGET", "LSL" };
            
            logger.info("building csv file process [" + fileName + "]");
            
            CsvFileWriterUtil.writeCVS("SLIM_EDC_DATA_BEGIN", headers, bodyList, "SLIM_EDC_DATA_END", fileName);

            logger.info("compress csv file process ....");
            
            GzCompressUtil.compress(new File(fileName));
            String gzFileName = fileName + ".gz";
            File gzFile = new File(gzFileName);

            // send to FTP Service
            ftpService.connect();
            ftpService.uploadFile(gzFile, getFtpConfigure().getFtpProcessParamExportPath());
            ftpService.disconnectFtp();
            logger.info("=============================================================================");

        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.toString());
            throw e;
        }

    }
    public class EdcKey{
        private String prd_seq_id;
        private String ope_id;
        private String mes_id;
        public String getPrd_seq_id() {
            return prd_seq_id;
        }
        public void setPrd_seq_id(String prd_seq_id) {
            this.prd_seq_id = prd_seq_id;
        }
        public String getOpe_id() {
            return ope_id;
        }
        public void setOpe_id(String ope_id) {
            this.ope_id = ope_id;
        }
        public String getMes_id() {
            return mes_id;
        }
        public void setMes_id(String mes_id) {
            this.mes_id = mes_id;
        }
        public EdcKey(String prd_seq_id, String ope_id, String mes_id) {
            super();
            this.prd_seq_id = prd_seq_id;
            this.ope_id = ope_id;
            this.mes_id = mes_id;
        }
        public EdcKey() {
            super();
        }
        
    }
    private List<Spc_ret_mfg_data> distinctEDCDatas(List<Spc_ret_mfg_data> spc_ret_mfg_datas) {
        List<Spc_ret_mfg_data> finalEdcList = new LinkedList<Spc_ret_mfg_data>();
        Map<EdcKey,Spc_ret_mfg_data> edcMap = new HashMap<EdcKey,Spc_ret_mfg_data>();
        for (Spc_ret_mfg_data edcData : spc_ret_mfg_datas) {
            EdcKey key = new EdcKey(edcData.getPrd_seq_id_fk(),edcData.getOpe_id_fk(),edcData.getMes_id_fk());
            Spc_ret_mfg_data value = edcMap.get(key);
            Timestamp time1 = edcData.getRpt_timestamp();
            if(value==null){
                edcMap.put(key, edcData);
            }else{
                Timestamp time2 = value.getRpt_timestamp();
                if(time1.after(time2)){
                    edcMap.put(key, edcData);
                }
            }
            
        }
        Set<Entry<EdcKey, Spc_ret_mfg_data>> edcSets = edcMap.entrySet();
        for (Entry<EdcKey, Spc_ret_mfg_data> edcSet : edcSets) {
            finalEdcList.add(edcSet.getValue());
        }
        return finalEdcList;
    }

    private String checkIsNull(String str) {
        return str == null ? "" : str;
    }

    private void getTimePeriod() {
        DateTime dt = new DateTime();

        DateTime endDt = dt.plusMinutes(endTimeMak);
        endTimestamp = new Timestamp(endDt.getMillis());

        DateTime beginDt = endDt.plusHours(-1);
        beginTimestamp = new Timestamp(beginDt.getMillis());

        strEndTime = getTimeFromDateTime(endDt);
        strBeginTime = getTimeFromDateTime(beginDt);

        logger.info("begin time:" + beginTimestamp);
        logger.info("end time :" + endTimestamp);
    }

    private String getTimeFromDateTime(DateTime dt) {
        return comInt2String(dt.getYear(), 4) + comInt2String(dt.getMonthOfYear(), 2)
                + comInt2String(dt.getDayOfMonth(), 2) + comInt2String(dt.getHourOfDay(), 2)
                + comInt2String(dt.getMinuteOfHour(), 2) + comInt2String(dt.getSecondOfMinute(), 2);
    }

    public static void main(String[] args) {
        new CsotExportProcessParamJob().getTimePeriod();
    }

    public Timestamp getBeginTimestamp() {
        return beginTimestamp;
    }

    public void setBeginTimestamp(Timestamp beginTimestamp) {
        this.beginTimestamp = beginTimestamp;
    }

    public Timestamp getEndTimestamp() {
        return endTimestamp;
    }

    public void setEndTimestamp(Timestamp endTimestamp) {
        this.endTimestamp = endTimestamp;
    }

    public String getStrBeginTime() {
        return strBeginTime;
    }

    public void setStrBeginTime(String strBeginTime) {
        this.strBeginTime = strBeginTime;
    }

    public String getStrEndTime() {
        return strEndTime;
    }

    public void setStrEndTime(String strEndTime) {
        this.strEndTime = strEndTime;
    }

    public FtpConfigure getFtpConfigure() {
        return ftpConfigure;
    }

    public void setFtpConfigure(FtpConfigure ftpConfigure) {
        this.ftpConfigure = ftpConfigure;
    }

    public String comInt2String(int value, int length) {
        String s = String.valueOf(value);
        if (s.length() > length) {
            throw new RuntimeException("length is too short.");
        } else if (s.length() == length) {
            return s;
        } else {
            char[] cc = new char[length];
            int i = 0;
            for (; i < length - s.length(); i++) {
                cc[i] = '0';
            }
            for (int j = 0; j < s.length(); i++, j++) {
                // System.out.println(i);
                cc[i] = s.charAt(j);
            }
            return new String(cc);
        }
    }

    public IFtpService getFtpService() {
        return ftpService;
    }

    public void setFtpService(IFtpService ftpService) {
        this.ftpService = ftpService;
    }
    public int getEndTimeMak() {
		return endTimeMak;
	}

	public void setEndTimeMak(int endTimeMak) {
		this.endTimeMak = endTimeMak;
	}

}
